home *** CD-ROM | disk | FTP | other *** search
/ BBS in a Box 7 / BBS in a Box - Macintosh - Volume VII (BBS in a Box) (January 1993).iso / Files / Prog / D-G / DA Skeleton 2.0.cpt / DASkeleton.p next >
Text File  |  1990-06-09  |  14KB  |  496 lines

  1. {    DASkeleton (v2.0)                                                                        }
  2. {    By: Michael J. Conrad                                                                    }
  3. {                                                                                                }
  4. {    This DA skeleton was written in THINK Pascal™ 3.01.                                }
  5. {                                                                                                }
  6. {    Intro.                                                                                        }
  7. {    -----                                                                                        }
  8. {    I wrote DASkeleton to aid new programmers in writing desk accessories. All        }
  9. {    you really have to do is add in what you want your DA to do. This skeleton         }
  10. {    takes care of almost all the normal things DAs must do.                                }
  11. {                                                                                                }
  12. {    DASkeleton is also good for experienced programmers who are tired of typing        }
  13. {    in all the basics every time they write a desk accessory.                            }
  14. {                                                                                                }
  15. {    DA Shell Users                                                                            }
  16. {    -------------                                                                            }
  17. {    If you use the DA Shell that comes on your THINK Pascal™ disk, there are some    }
  18. {    things you must change or take into consideration:                                    }
  19. {                                                                                                }
  20. {        1.    The formula for figuring the owned resources must be changed. For the        }
  21. {            DA Shell, your DA's refNum must be calculated as:                            }
  22. {                                                                                                }
  23. {                            refNum:=Abs(dce^.dCtlRefNum)-1;                                }
  24. {                                                                                                }
  25. {            For the actual desk accessory, it must be calculated as:                        }
  26. {                                                                                                }
  27. {                            refNum:=Abs(-dce^.dCtlRefNum)-1;                            }
  28. {                                                                                                }
  29. {            Note that the way the instructions say to do it in the DA Shell is wrong.    }
  30. {            The THINK Pascal™ user's manual explains it correctly.                        }
  31. {                                                                                                }
  32. {        2.     When handling mouse down events in the DA Shell, you must have your        }
  33. {            DA handle it as "InContent". As a real DA, you must have it as                 }
  34. {            "inSysWindow". You must physically change the case constants in the         }
  35. {            doMouseDown procedure.                                                        }
  36. {                                                                                                }
  37. {        4.     When using the DA Shell, you must create "dummy" procedures for            }
  38. {            RememberA4, SetUpA4, and RestoreA4. This is because only the             }
  39. {            DRVRRuntime library contains these procedures.                                }
  40. {                                                                                                }
  41. {        3.    Read the instructions in the DAShell and the THINK Pascal™ users manual    }
  42. {            for more information.                                                            }
  43. {                                                                                                }
  44. {    Version 2.0 Changes                                                                        }
  45. {    -------------------                                                                        }
  46. {                                                                                                }
  47. {    The changes in 2.0 are really too numerous to mention. But here are a few key    }
  48. {    changes.                                                                                    }
  49. {                                                                                                }
  50. {        √    Code is broken into more separate procedures.                                }
  51. {        √    Fixed menu bug where it wouldn't go away when DA was closed.                }
  52. {        √    Fixed reentrancy problems.                                                        }
  53. {        √    Set the dCtlFlags manually now. This kind of goes with the one above.        }
  54. {        √    Included a hierarchical menu.                                                    }
  55. {                                                                                                }
  56. {    Where Did All The Comments Go?                                                        }
  57. {    ------------------------------                                                        }
  58. {    I didn't add as many comments in version 2.0 as there has been in previous        }
  59. {    versions. This is because the comments tended to "get in the way". If you're        }
  60. {    writing a DA, you should already be fairly familiar with programming the            }
  61. {    Macintosh™, so most of the comments aren't needed anyway.                        }
  62. {                                                                                                }
  63. {    Using Hierarchical Menus In DA's                                                        }
  64. {    ---------------------------                                                            }
  65. {    If you use the DA Shell, be sure you use the revised one. The latest one to date    }
  66. {    and the only one which supports hierarchical menus was revised on 5/22/90 by    }
  67. {    Dennis King (DLK). It can be found in the Symantec™ forum on CIS.                     }
  68. {                                                                                                }
  69. {    Watch Out!!                                                                                }
  70. {    -----------                                                                                }
  71. {    If you use the cdev hierDA (A.K.A. DA Menuz), you must disable it before             }
  72. {    attempting to run your DA in the DA Shell. This is because hierDA automatically    }
  73. {    opens a DA when it thinks one of its menus is being used. And if one of your        }
  74. {    hierarchical menus happens to have the same id as an exhisting DA, the DA will    }
  75. {    open suddenly on you, and may cause a system crash (it does on my machine).        }
  76. {                                                                                                }
  77. {    Non-THINK Pascal Users                                                                    }
  78. {    ----------------------                                                                    }
  79. {    You can still use this DA Skeleton, but...most other pascal compilers don't             }
  80. {    allow the use of global data in drivers.                                                    }
  81. {                                                                                                }
  82. {    Mentionware                                                                                }
  83. {    ------------                                                                                }
  84. {    If you use this as your skeleton, all I ask for is that either in your about box        }
  85. {    or documentation, you mention that you used DASkeleton.                            }
  86. {                                                                                                }
  87. {    Credits                                                                                    }
  88. {    -------                                                                                    }
  89. {    Thanks to Dennis King, who passed along some bugs he noticed and help me out        }
  90. {    with the menu and bit setting problems. He is also responsible for revising the        }
  91. {    DA Shell to watch for hierarchical menus.                                                }
  92. {                                                                                                }
  93. {    In Closing                                                                                    }
  94. {    ---------                                                                                    }
  95. {    If you find any bugs _PLEASE_ let me know so I can fix them. I would rather        }
  96. {    fix them instead of having someone else spend hours trying to fix one of my        }
  97. {    mistakes!                                                                                    }
  98. {                                                                                                }
  99. {    DASkeleton is Copyright (c) 1989-90, Michael Conrad. All Rights Reserved.        }
  100. {    CIS: [73457,426]        GENIE: M.CONRAD1        Amer.On: MichaelC50            }
  101.  
  102. unit DASkeleton;
  103.  
  104. interface
  105.  
  106.     uses
  107.         Globals, MiscRoutines;
  108.  
  109. {All drivers and code resources in LSP must have a function or procedure called 'main'}
  110.     function main (theDce: DCtlPtr; iopb: ParmBlkPtr; sel: integer): OSErr;
  111.  
  112. implementation
  113.  
  114. {--------------------------------•--------------------------------}
  115.  
  116. {Our window just got uncovered, so redraw the window}
  117.     procedure UpdateWindow;
  118.         const
  119.             Line1 = 'DA Skeleton';
  120.             Line2 = 'Version 2.0';
  121.             Line3 = 'Written in THINK Pascal™ 3.0';
  122.             Line4 = 'Copyright (c) 1989-90';
  123.             Line5 = 'By: Michael J. Conrad';
  124.     begin
  125.         SetPort(window);
  126.  
  127.         TextSize(12);
  128.         TextFont(geneva);
  129.         TextFace([Outline]);
  130.         MoveTo(90, 20);
  131.         DrawString(Line1);
  132.         TextFace([]);
  133.         TextFace([italic]);
  134.         MoveTo(95, 34);
  135.         DrawString(Line2);
  136.         TextFace([]);
  137.         MoveTo(38, 50);
  138.         DrawString(Line3);
  139.  
  140.         MoveTo(5, 60);
  141.         LineTo(255, 60);
  142.  
  143.         TextSize(9);
  144.         MoveTo(10, 77);
  145.         DrawString(Line4);
  146.         MoveTo(10, 90);
  147.         DrawString(Line5);
  148.  
  149.         DrawControls(window);
  150.     end;
  151.  
  152. {--------------------------------•--------------------------------}
  153.  
  154.     procedure DoButton (theControl: ControlHandle);
  155.         var
  156.             Part: integer;
  157.             err: integer;
  158.             thePoint: Point;
  159.  
  160.     begin
  161.         Part := TrackControl(theControl, thePoint, nil);
  162.         if (Part = InButton) then
  163.             begin
  164.                 err := CloseDriver(dce^.dCtlRefNum);
  165.             end;
  166.     end;
  167.  
  168. {--------------------------------•--------------------------------}
  169.  
  170.     procedure doMouseDown (thePoint: Point);
  171.         var
  172.             thePart: integer;
  173.             where: integer;
  174.             theControl: ControlHandle;
  175.  
  176.     begin
  177.         thePart := FindWindow(thePoint, window);
  178.  
  179.         if (thePart = inContent) then
  180.             begin
  181.                 GlobalToLocal(thePoint);
  182.                 where := FindControl(thePoint, window, theControl);
  183.                 if (theControl = theButton) then
  184.                     DoButton(theControl);
  185.             end;
  186.     end;
  187.  
  188. {--------------------------------•--------------------------------}
  189.  
  190.     procedure DoKeyDown (event: EventPtr);
  191.         var
  192.             ch: char;
  193.  
  194.     begin
  195.         ch := Chr(BitAnd(event^.message, CharCodeMask));
  196.         if BitAnd(event^.modifiers, CmdKey) <> 0 then
  197.             if event^.what <> autoKey then
  198.                 begin
  199.                     case ch of                                {This covers the standard command keys}
  200.                         'z', 'Z':                                 {in the Edit menu.}
  201.                             SysBeep(1);
  202.                         'x', 'X': 
  203.                             SysBeep(1);
  204.                         'c', 'C': 
  205.                             SysBeep(1);
  206.                         'v', 'V': 
  207.                             SysBeep(1);
  208.     {Insert other command keys here}
  209.                     end;
  210.                 end;
  211.     end;
  212.  
  213. {--------------------------------•--------------------------------}
  214.  
  215.     procedure DoActivate (event: EventPtr);
  216.     begin
  217.         if BitAnd(event^.modifiers, ActiveFlag) <> 0 then
  218.             begin
  219.                 InsertMenu(ourMenu, 0);
  220.                 InsertMenu(hierMenu, -1);
  221.                 DrawMenuBar;
  222.             end
  223.         else
  224.             begin
  225.                 DeleteMenu(dce^.dCtlMenu);
  226.                 DeleteMenu(hierMID);
  227.                 DrawMenuBar;
  228.             end;
  229.     end;
  230.  
  231. {--------------------------------•--------------------------------}
  232.  
  233. {This routine handles the events that are passed to us via control}
  234.     procedure doEvent (event: EventPtr);
  235.     begin
  236.         case event^.what of
  237.             keyDown: 
  238.                 DoKeyDown(event);
  239.             mouseDown: 
  240.                 doMouseDown(event^.where);
  241.             UpdateEvt: 
  242.                 begin
  243.                     SetPort(window);
  244.                     BeginUpdate(window);
  245.                     UpdateWindow;
  246.                     EndUpdate(window);
  247.                 end;
  248.             ActivateEvt: 
  249.                 DoActivate(event);
  250.         end;
  251.     end;
  252.  
  253. {--------------------------------•--------------------------------}
  254.  
  255. {Put up an about window an brag about ourselves}
  256.     procedure DoAbout (window: WindowPtr);
  257.         var
  258.             AboutDlg: DialogPtr;
  259.             savePort: GrafPtr;
  260.             item: integer;
  261.             Flag: Boolean;
  262.  
  263.     begin
  264.         GetPort(savePort);
  265.         HideWindow(window);
  266.  
  267.         AboutDlg := GetNewDialog(rslvid(ABOUTID), nil, WindowPtr(-1));
  268.         CenterWindow(AboutDlg, True, True);
  269.         ShowWindow(AboutDlg);
  270.         SetPort(AboutDlg);
  271.  
  272.         Flag := True;
  273.         while Flag do
  274.             begin
  275.                 ModalDialog(@updateFilter, item);
  276.                 if (item = 1) then
  277.                     Flag := False;
  278.             end;
  279.  
  280.         DisposDialog(AboutDlg);
  281.         ShowWindow(window);
  282.         SetPort(savePort);
  283.     end;
  284.  
  285. {--------------------------------•--------------------------------}
  286.  
  287.     procedure InitWindow;
  288.     begin
  289.     {Get our window from the resource. (a WIND resource)}
  290.         window := GetNewWindow(rslvid(MAINWINDOW), nil, WindowPtr(-1));
  291.         CenterWindow(window, True, False);
  292.         SetWTitle(window, TITLE);
  293.         ShowWindow(window);
  294.         SetPort(window);
  295.  
  296.         WindowPeek(window)^.windowkind := dce^.dCtlRefNum;
  297.         dce^.dCtlWindow := WindowPtr(window);
  298.  
  299.         theButton := GetNewControl(rslvid(BUTTONID), window);
  300.     end;
  301.  
  302. {--------------------------------•--------------------------------}
  303.  
  304.     procedure InitMenus;
  305.         var
  306.             theID: integer;
  307.  
  308.     begin
  309.         theID := rslvid(MENUID);
  310.         ourMenu := GetMenu(theID);
  311.         ourMenu^^.menuId := theID;
  312.         dce^.dCtlMenu := theID;
  313.         InsertMenu(ourMenu, 0);
  314.  
  315.         hierMenu := GetMenu(rslvid(HIERID));
  316.         hierMenu^^.menuId := hierMID;
  317.         InsertMenu(hierMenu, -1);
  318.  
  319.         DrawMenuBar;
  320.     end;
  321.  
  322. {--------------------------------•--------------------------------}
  323.  
  324.     procedure HandleMenus (theMenu, theItem: integer);
  325.     begin
  326.         if (theMenu = dce^.dCtlMenu) then
  327.             case theItem of
  328.                 1: 
  329.                     DoAbout(window);
  330.                 2: 
  331.                     SysBeep(10);
  332.                 3: 
  333.                     SysBeep(10);
  334.                 4: 
  335.                     SysBeep(10);
  336.                 otherwise
  337.                     ;
  338.             end;
  339.         if (theMenu = hierMID) then
  340.             case theItem of
  341.                 1: 
  342.                     SysBeep(1);
  343.                 2: 
  344.                     ;
  345.                 3: 
  346.                     ;
  347.                 otherwise
  348.                     ;
  349.             end;
  350.         HiliteMenu(0);
  351.     end;
  352.  
  353. {--------------------------------•--------------------------------}
  354.  
  355. {////////////  Driver Routines Are Below Here  ////////////}
  356.  
  357. {--------------------------------•--------------------------------}
  358.  
  359. {This procedure handles our open call. It puts up a window and}
  360. {gets our menu for our DA. In addition it figures the screen size}
  361. {and our drivers reference number.}
  362.     procedure open (iopb: ParmBlkPtr);
  363.     begin
  364.         window := WindowPtr(dce^.dCtlWindow);
  365.         if not DAOpen then
  366.             begin
  367.                 DAOpen := True;
  368.                 screenBounds := GetScrSize;    {Get the screen size}
  369.                 InitWindow;
  370.                 InitMenus;
  371.             end
  372.         else
  373.             SelectWindow(window);
  374.     end;
  375.  
  376. {--------------------------------•--------------------------------}
  377.  
  378. {This procedure handles control calls from the dce. Such as}
  379. {menus, and other events.}
  380.     procedure control (iopb: ParmBlkPtr);
  381.     begin
  382.         window := WindowPtr(dce^.dCtlWindow);
  383.         SetPort(window);
  384.  
  385.         case iopb^.csCode of
  386.             accEvent: 
  387.                 doEvent(Pointer(iopb^.ioMisc));
  388.             accRun: 
  389.                 begin
  390. {*** Your DA is getting time from the system...Do whatever ***}
  391.                 end;
  392.             accMenu: 
  393.                 HandleMenus(iopb^.csParam[0], iopb^.csParam[1]);
  394.             accUndo: 
  395.                 SysBeep(1);
  396.             accCut: 
  397.                 SysBeep(1);
  398.             accCopy: 
  399.                 SysBeep(1);
  400.             accPaste: 
  401.                 SysBeep(1);
  402.             accClear: 
  403.                 SysBeep(1);
  404.         end;
  405.     end;
  406.  
  407. {--------------------------------•--------------------------------}
  408.  
  409. {This routine handles our close call. It takes down our window}
  410. {and clears the menu bar. Always clean up behind yourself!!}
  411.     procedure close (iopb: ParmBlkPtr);
  412.     begin
  413.         window := WindowPtr(dce^.dCtlWindow);
  414.         if (DAOpen) then
  415.             begin
  416.                 DeleteMenu(hierMID);
  417.                 DeleteMenu(dce^.dCtlMenu);
  418.                 DrawMenuBar;
  419.  
  420.                 ReleaseResource(Handle(ourMenu));        {Just for GP}
  421.                 ReleaseResource(Handle(hierMenu));
  422.  
  423.                 dce^.dCtlMenu := 0;
  424.                 ourMenu := nil;
  425.                 hierMenu := nil;
  426.  
  427.                 DisposeWindow(window);
  428.                 dce^.dCtlWindow := nil;
  429.  
  430.                 DAOpen := False;
  431.             end;
  432.     end;
  433.  
  434. {--------------------------------•--------------------------------}
  435.  
  436.     procedure prime (iopb: ParmBlkPtr);
  437.     begin
  438. {Only "real" drivers use this call. We don't need it in this DA}
  439.     end;
  440.  
  441. {--------------------------------•--------------------------------}
  442.  
  443.     procedure status (iobp: ParmBlkPtr);
  444.     begin
  445. {Only "real" drivers use this call. We don't need it in this DA}
  446.     end;
  447.  
  448. {--------------------------------•--------------------------------}
  449.  
  450.     function main (theDce: DCtlPtr; iopb: ParmBlkPtr; sel: integer): OSErr;
  451.         const
  452.             drvrOpen = 0;
  453.             drvrPrime = 1;
  454.             drvrControl = 2;
  455.             drvrStatus = 3;
  456.             drvrClose = 4;
  457.  
  458.             dCtlEnable = 2;                        {Enable/Disable control calls}
  459.             dNeedTime = 5;                        {Give us some time from the system}
  460.     begin
  461.         main := 0;                                {No problems...}
  462.         RememberA4;
  463.  
  464.         BitClr(@theDCE^.dCtlFlags, dCtlEnable);
  465.  
  466.         dce := theDce;
  467.  
  468.         case sel of
  469.             drvrOpen: 
  470.                 begin
  471.                     if (dce^.dCtlStorage = nil) then    {For some reason, we could not get enough    }
  472.                         begin                                {memory to run. Exit the DA. You could put}
  473.                             SysBeep(5);                    {a dialog up stating that the DA can't run,but}
  474.                             main := -108;                    {you can't use any globals!!}
  475.                             Exit(main);
  476.                         end;
  477.                     open(iopb);                    {Call OPEN procedure}
  478.                 end;
  479.             drvrPrime: 
  480.                 prime(iopb);
  481.             drvrControl: 
  482.                 control(iopb);                    {Handle a CONTROL call for our DA}
  483.             drvrStatus: 
  484.                 status(iopb);
  485.             drvrClose: 
  486.                 close(iopb);                    {Close our DA}
  487.         end;
  488.  
  489.         theDce^.dCtlDelay := 60;                    {Get us some time}
  490.         BitSet(@theDCE^.dCtlFlags, dCtlEnable);    {Set our flags}
  491.         BitSet(@theDCE^.dCtlFlags, dNeedTime);
  492.     end;
  493.  
  494. {--------------------------------•--------------------------------}
  495.  
  496. end.